export let Vue

class MyRouter {
	constructor(options) {
		this.$options = options
		this.routeMap = {}
		this.app = new Vue({
			data() {
				return {
					current: '/'
				}
			}
		})
	}
	static install(_Vue) {
		Vue = _Vue
		Vue.mixin({
			beforeCreate() {
				if (this.$options.router) {
					Vue.prototype.$router = this.$options.router
					Vue.prototype.$router.push = this.$options.router.push
					this.$options.router.init()
				}
			}
		})
	}
	push(path) {
		const {
			mode
		} = this.$options
		const _path = path || '/'
		if (mode === 'history') {
			window.history.pushState(_path, null, _path)
			this.app.current = _path
		} else {
			window.location.hash = '#' + _path
		}
	}
	init() {
		this.createRouteMap()
		this.bindEvent()
		this.registerComponents()
	}
	createRouteMap() {
		this.$options.routes.forEach(item => {
			this.routeMap[item.path] = item.component
		})
	}
	bindEvent() {
		const {
			mode
		} = this.$options
		window.addEventListener('load', this.onLocationChange.bind(this))
		const event = mode === 'history' ? 'popstate' : 'hashchange'
		window.addEventListener(event, this.onLocationChange.bind(this))
	}
	onLocationChange() {
		const {
			mode
		} = this.$options
		const isHistory = mode === 'history'
		let path = '/'
		if (isHistory) {
			path = window.location.pathname
		} else {
			if (window.location.hash) {
				path = window.location.hash.slice(1)
			} else {
				window.location.href = '#/'
			}
		}
		this.app.current = path || '/'
	}

	registerComponents() {
		const _this = this
		Vue.component('router-link', {
			props: {
				to: {
					type: String,
					required: true,
					default: ''
				}
			},
			render(h) {
				const {
					mode
				} = _this.$options
				const isHistory = mode === 'history'
				const attrs = isHistory ? {
					href: ''
				} : {
					href: '#' + this.to
				}
				const clickHandler = e => {
					e.preventDefault()
					const _path = this.to || '/'
					window.history.pushState(_path, null, _path)
					_this.app.current = this.to
				}
				const on = isHistory ?
					{
						click: clickHandler
					} :
					{}
				return h(
					'a', {
						class: {
							'router-link': true
						},
						attrs,
						on
					},
					[this.$slots.default]
				)
			}
		})
		Vue.component('router-view', {
			render(h) {
				const Component = _this.routeMap[_this.app.current]
				return h(Component)
			}
		})
	}
}

export default MyRouter
